package cn.learn.pay.wechat.util;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.Xpp3DomDriver;
import com.thoughtworks.xstream.io.xml.XppDriver;
import com.thoughtworks.xstream.security.AnyTypePermission;

import javax.validation.Valid;
import java.io.Writer;

/**
 * 处理微信的xml格式工具类
 *
 * @author huangyezhan
 * @version 1.0
 * @date 2021年08月26日21:42
 */
public class HandlerWeChatXmlUtil {
    private HandlerWeChatXmlUtil() {
    }

    private static final XStream STREAM = new XStream(new Xpp3DomDriver(new NoNameCoder()));

    private static final XStream X_STREAM = new XStream(new XppDriver(new NoNameCoder()) {
        @Override
        public HierarchicalStreamWriter createWriter(Writer out) {
            return new PrettyPrintWriter(out) {
                final boolean cdata = true;

                @Override
                public void startNode(String name, Class clazz) {
                    super.startNode(name, clazz);
                }

                @Override
                public String encodeNode(String name) {
                    return name;
                }

                @Override
                protected void writeText(QuickWriter writer, String text) {
                    if (cdata) {
                        writer.write("<![CDATA[");
                        writer.write(text);
                        writer.write("]]>");
                    } else {
                        writer.write(text);
                    }
                }
            };
        }
    });

    /**
     * 带上![CDATA[] 的方法
     *
     * @param bean 微信支付的相关实体
     * @param cls  实体类型
     * @return 转换成xml字符串
     */
    public static String generateXmlBySign(@Valid Object bean, Class<?> cls) {
        X_STREAM.alias("xml", cls);
        return X_STREAM.toXML(bean);
    }

    /**
     * bean转成xml
     *
     * @param bean 微信支付的相关实体
     * @return 转换成xml字符串
     */
    public static String generateXml(@Valid Object bean, Class<?> cls) {
        STREAM.alias("xml", cls);
        return STREAM.toXML(bean);
    }

    /**
     * 解析xml成bean对象
     *
     * @param xml xml字符串
     * @param <T> 泛型
     * @return 返回结果
     */
    public static <T> T parseXml2Bean(String xml, Class<T> clz) {
        XStream xStream = new XStream(new Xpp3DomDriver(new NoNameCoder()));
        xStream.addPermission(AnyTypePermission.ANY);
        xStream.alias("xml", clz);
        Object o = xStream.fromXML(xml);
        return clz.cast(o);
    }

}
